/*
 * Created on 11/Abr/2004
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package org.cyborgas.xmltool.tabsheets;

import java.util.ArrayList;

import org.cyborgas.xmltool.MainWindow;
import org.cyborgas.xmltool.XmlLabelProvider;
import org.cyborgas.xmltool.XmlNodeListContentProvider;
import org.cyborgas.xmltool.actions.XpathCopyResultsAction;
import org.dom4j.Node;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Text;
import org.jaxen.JaxenException;
import org.jaxen.SimpleNamespaceContext;
import org.jaxen.XPath;
import org.jaxen.dom4j.Dom4jXPath;


/**
 * @author rino
 *
 */
public class XPathTab {

	private MainWindow mainWindow;

	private java.util.List lastResults;

	// controls
	private Label valueLabel;
	private Combo valueOfCombo;
	private Text valueText;
	private Label queryLabel;
	private Combo queryText;
	private Label label2;
	private Button evaluateButton;
	private Combo evaluateWhereCombo;
	private Label namespacesLabel;
	private ListViewer namespacesList;
	private Label resultsLabel;
	private ListViewer resultsList;


	/**
	 * @param parent
	 */
	public XPathTab(MainWindow window) {
		this.mainWindow = window;
	}
	
	public Composite createControls(Composite parent) {
		GridData gridData;
		final int LEFT_LABEL_WIDTH = 65;

        // containers start
		SashForm mainPane = new SashForm(parent, SWT.VERTICAL);

		Composite topPane = new Composite(mainPane, SWT.NULL);
		GridLayout topPaneLayout = new GridLayout();
		topPaneLayout.numColumns = 2;
		topPaneLayout.marginHeight = 5;
		topPaneLayout.marginWidth = 0;
		topPaneLayout.horizontalSpacing = 0;
		topPane.setLayout(topPaneLayout);

		Composite bottomPane = new Composite(mainPane, SWT.NULL);
		GridLayout bottomPaneLayout = new GridLayout();
		bottomPaneLayout.numColumns = 3;
		bottomPaneLayout.marginHeight = 0;
		bottomPaneLayout.marginWidth = 0;
		bottomPaneLayout.horizontalSpacing = 0;
		bottomPane.setLayout(bottomPaneLayout);

		// containers end

		// controls start
		valueLabel = new Label(topPane, SWT.NONE);
		valueLabel.setText("&Value");
		gridData = new GridData();
		gridData.widthHint = LEFT_LABEL_WIDTH;
//		gridData.horizontalAlignment = GridData.FILL;
//		gridData.grabExcessHorizontalSpace = true;
		valueLabel.setLayoutData(gridData);

		valueOfCombo = new Combo(topPane, SWT.READ_ONLY);
		valueOfCombo.setItems(new String[] { "Text", "Element", "XML" });
		valueOfCombo.select(0);
		gridData = new GridData();
		gridData.horizontalIndent = 5;
		valueOfCombo.setLayoutData(gridData);

		valueText =
			new Text(
				topPane,
				SWT.BORDER
					| SWT.MULTI
					| SWT.V_SCROLL
					| SWT.WRAP
					| SWT.READ_ONLY);
		gridData = new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		valueText.setLayoutData(gridData);

		queryLabel = new Label(bottomPane, SWT.NONE);
		queryLabel.setText("&XPath query");
		gridData = new GridData();
		gridData.widthHint = LEFT_LABEL_WIDTH;
		gridData.horizontalAlignment = GridData.FILL;
		gridData.horizontalIndent = 0;
		queryLabel.setLayoutData(gridData);

		queryText = new Combo(bottomPane, SWT.DROP_DOWN);
		queryText.setText("");
		gridData = new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		gridData.horizontalIndent = 5;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		queryText.setLayoutData(gridData);

		label2 = new Label(bottomPane, SWT.NONE);
		label2.setText("");
		gridData = new GridData();
		gridData.horizontalIndent = 0;
		label2.setLayoutData(gridData);

		evaluateButton = new Button(bottomPane, SWT.PUSH);
		evaluateButton.setText("&Evaluate");
		gridData = new GridData();
		gridData.horizontalIndent = 5;
		evaluateButton.setLayoutData(gridData);

		evaluateWhereCombo = new Combo(bottomPane, SWT.READ_ONLY);
		evaluateWhereCombo.setItems(new String[] { "Document", "Selection" });
		evaluateWhereCombo.select(0);
		gridData = new GridData();
		gridData.horizontalIndent = 5;
		evaluateWhereCombo.setLayoutData(gridData);

		namespacesLabel = new Label(bottomPane, SWT.NONE);
		namespacesLabel.setText("Namespaces");
		gridData = new GridData();
		gridData.horizontalIndent = 0;
		gridData.horizontalSpan = 3;
		namespacesLabel.setLayoutData(gridData);

		List namespacesListWidget = new List(bottomPane, SWT.BORDER | SWT.V_SCROLL);
		gridData = new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalIndent = 0;
		gridData.horizontalSpan = 3;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = false;
		namespacesListWidget.setLayoutData(gridData);
		namespacesList = new ListViewer(namespacesListWidget);
		
		resultsLabel = new Label(bottomPane, SWT.NONE);
		resultsLabel.setText("Results");
		gridData = new GridData();
		gridData.horizontalIndent = 0;
		gridData.horizontalSpan = 3;
		resultsLabel.setLayoutData(gridData);

		List resultsListWidget = new List(bottomPane, SWT.BORDER | SWT.V_SCROLL);
//		resultsList.setItems(new String[] { "Item 1", "Item 2", "Item 2" });
		gridData = new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalIndent = 0;
		gridData.horizontalSpan = 3;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		resultsListWidget.setLayoutData(gridData);
		resultsList = new ListViewer(resultsListWidget);
		resultsList.setContentProvider(new XmlNodeListContentProvider());
		resultsList.setLabelProvider(new XmlLabelProvider());


		// controls end

		mainPane.setWeights(new int[] { 1, 3 });

		// events start
		mainWindow.docTreeView
			.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection sel =
					(IStructuredSelection) event.getSelection();
				Node selNode = (Node) sel.getFirstElement();
				if (selNode != null) {
					setValueText(selNode);
					IStructuredSelection resultsSel =
						(IStructuredSelection) resultsList.getSelection();
					if (!selNode.equals(resultsSel.getFirstElement())) {
						resultsList.setSelection(null);
					}
				}
			}
		});
		
		valueOfCombo.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				Node selNode = mainWindow.getSelectedNode();
				setValueText(selNode);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});

		queryText.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent event) {
			}
			public void widgetDefaultSelected(SelectionEvent event) {
				processXPathQuery();
			}
		});

		evaluateButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent event) {
				processXPathQuery();
			}
			public void widgetDefaultSelected(SelectionEvent event) {
			}
		});

		resultsList
			.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection sel =
					(IStructuredSelection) event.getSelection();
				if (sel.getFirstElement() instanceof Node) {
					Node selNode = (Node) sel.getFirstElement();
					mainWindow.docTreeView.setSelection(new StructuredSelection(selNode), true);
				}
			}
		});

		// events end

		return mainPane;
	}
	
	public MenuManager createMenu() {
		MenuManager menu = new MenuManager("X&Path");
		menu.add(new XpathCopyResultsAction(mainWindow, this));

		return menu;
	}

	public java.util.List getResults() {
		return lastResults;
	}

	private void updateQueryHistory(String string) {
		int previous = queryText.indexOf(string); 
		if (previous != -1) {
			queryText.remove(previous);
			queryText.setText(string);
		}
		queryText.add(string, 0);
	}

	private java.util.List evaluateQuery(String query, Node where) {
		java.util.List list = null;
		Node node = null;
		if (where == null) {
			node = mainWindow.xmlDocument.getDocument();
		} else {
			node = where;
		}

		try {
		    XPath xpath = new Dom4jXPath(query);
			SimpleNamespaceContext context = new SimpleNamespaceContext();
	        context.addNamespace("vot", "http://www.ivoa.net/xml/VOTable/v1.1");
	        xpath.setNamespaceContext(context);
		    list = xpath.selectNodes(node);
//			list = node.selectNodes(query);
		} catch (JaxenException e) {
			list = new ArrayList();
			list.add(e.getMessage());
		}

		lastResults = list;
		return list;

	}

	private void processXPathQuery() {
		updateQueryHistory(queryText.getText());
		Node where = null;
		if (evaluateWhereCombo.getSelectionIndex() != 0) {
			where = mainWindow.getSelectedNode();
		}
		resultsList.setInput(evaluateQuery(queryText.getText(), where));
	}

	private void setValueText(Node node) {
		if (node != null) {
			if (valueOfCombo.getSelectionIndex() == 0) {
				valueText.setText(node.getText());
			} else if (valueOfCombo.getSelectionIndex() == 1) {
				valueText.setText(node.getStringValue());
			} else if (valueOfCombo.getSelectionIndex() == 2) {
				valueText.setText(node.asXML());
			}
		} else {
			valueText.setText("");
		}
	}


}
